package com.hzjh.base.utils.eventbus

import android.view.View
import androidx.lifecycle.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.launch

object FlowBus {
    private val busMap = mutableMapOf<String, EventBus<*>>()
    private val busStickMap = mutableMapOf<String, StickEventBus<*>>()

    @Synchronized
    fun <T> with(key: String): EventBus<T> {
        var eventBus = busMap[key]
        if (eventBus == null) {
            eventBus = EventBus<T>(key)
            busMap[key] = eventBus
        }
        return eventBus as EventBus<T>
    }

    @Synchronized
    fun <T> withStick(key: String): StickEventBus<T> {
        var eventBus = busStickMap[key]
        if (eventBus == null) {
            eventBus = StickEventBus<T>(key)
            busStickMap[key] = eventBus
        }
        return eventBus as StickEventBus<T>
    }


    fun boolFlowBusNotify(tag: String, bool: Boolean = true) {
        with<Boolean>(tag)
            .post(
                MainScope(), bool
            )
    }

    fun intFlowBusNotify(tag: String, data: Int = 0) {
        with<Int>(tag)
            .post(
                MainScope(), data
            )
    }

    //真正实现类
    open class EventBus<T>(private val key: String) : LifecycleObserver {

        //私有对象用于发送消息
        private val _events: MutableSharedFlow<T> by lazy {
            obtainEvent()
        }

        //暴露的公有对象用于接收消息
        val events = _events.asSharedFlow()

        private val actions by lazy {
            mutableMapOf<Any, (t: T) -> Unit>()
        }

        init {
            MainScope().launch {
                events.collect {
                    try {
                        actions.values.forEach { action ->
                            action.invoke(it)
                        }
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }
                }
            }
        }

        open fun obtainEvent(): MutableSharedFlow<T> =
            MutableSharedFlow(0, 1, BufferOverflow.DROP_OLDEST)

        //主线程接收数据
        fun register(lifecycleOwner: LifecycleOwner, action: (t: T) -> Unit) {
            lifecycleOwner.lifecycle.addObserver(this)
            lifecycleOwner.lifecycleScope.launch {
                events.collect {
                    try {
                        action(it)
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }
                }
            }
        }

        fun register(view: View, action: (t: T) -> Unit) {
            actions[view] = action
            view.addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener {
                override fun onViewAttachedToWindow(v: View) {

                }

                override fun onViewDetachedFromWindow(v: View) {
                    actions.remove(v)
                    onDestroy()
                }

            })
        }

//        /**
//         * 主线程接收数据
//         * @note 当前页面收发消息实时
//         * 从其他页面返回，只能收到该类消息的最后一条
//         */
//        fun registerWhenStarted(lifecycleOwner: LifecycleOwner, action: (t: T) -> Unit) {
//            lifecycleOwner.lifecycle.addObserver(this)
//            lifecycleOwner.lifecycleScope.launchWhenStarted {
//                events.collect {
//                    try {
//                        action(it)
//                    } catch (e: Exception) {
//                        e.printStackTrace()
//                        YYLogUtils.e("FlowBus - Error:$e")
//                    }
//                }
//            }
//        }

        //协程中发送数据
        suspend fun post(event: T) {
            _events.emit(event)
        }

        //主线程发送数据
        fun post(scope: CoroutineScope, event: T) {
            scope.launch {
                _events.emit(event)
            }
        }


        //自动销毁
        @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
        fun onDestroy() {
            val subscriptCount = _events.subscriptionCount.value
            if (subscriptCount <= 0)
                busMap.remove(key)
        }
    }

    class StickEventBus<T>(key: String) : EventBus<T>(key) {
        override fun obtainEvent(): MutableSharedFlow<T> =
            MutableSharedFlow(1, 1, BufferOverflow.DROP_OLDEST)
    }

}